package com.javacv4axe.example;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.imageio.ImageIO;

import org.axe.util.LogUtil;
import org.axe.util.StringUtil;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.RectVector;
import org.bytedeco.javacpp.opencv_imgproc;
import org.bytedeco.javacpp.opencv_objdetect.CascadeClassifier;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import com.javacv4axe.core.AsynchronousFrameHandler;
import com.javacv4axe.core.FramePack;
import com.javacv4axe.util.Base64Util;

/**
 * 人脸检测Handler
 */
public class FaceDetectHandler extends AsynchronousFrameHandler{
	// 读取opencv人脸检测器
	private CascadeClassifier cascade = null;
	//java2d转换器，用来mat和bufferedimage互转
	private Java2DFrameConverter java2dConvert = new Java2DFrameConverter();

	public FaceDetectHandler() {
		String cascadeClassifierXmlPath = cascadeClassifierXmlPath();
		if(!new File(cascadeClassifierXmlPath).exists()){
			LogUtil.log("分类器训练文件不存在："+cascadeClassifierXmlPath);
		}else{
			cascade = new CascadeClassifier(cascadeClassifierXmlPath);
			if(debug()){
				LogUtil.log(name()+"，初始化完成");
			}
		}
	}
	
	@Override
	public final boolean handle(FramePack framePack) {
		if(debug()){
			LogUtil.log(name()+" cascade="+cascade);
		}
		if(cascade == null){
			return false;//没发现
		}
		try {
			// 摄像头是彩色的图像，要先灰度化
			Mat grayMat = new Mat();
			//取上下文中的editFrame，因为editFrame可能不是全画幅，这样效率高一些
			opencv_imgproc.cvtColor((Mat)framePack.getEditFrame().opaque, grayMat, opencv_imgproc.COLOR_BGRA2GRAY);
			opencv_imgproc.equalizeHist(grayMat, grayMat);// 均衡化直方图
			// 检测人脸
			RectVector faces = new RectVector();
			cascade.detectMultiScale(grayMat.getUMat(0), faces);
			if(debug()){
				LogUtil.log(name()+" faces detected:"+faces.size());
			}
			if(faces.size() > 0){
				//生成base64
				String base64 = getBase64(framePack.getEditFrame());
				if(StringUtil.isNotEmpty(base64)){
					boolean success = faceDetectedBase64(framePack.getEditFrame(),base64);
					return success;
				}else{
					return false;
				}
			}
			return false;
		} catch (Exception e) {
			LogUtil.error(e);
			return false;
		}
	}
	
	@Override
	public String name() {
		return "人脸识别Handle Timer";
	}

	public boolean faceDetectedBase64(Frame frame,String base64) {
		LogUtil.log("发现人脸:"+base64);
		return true;
	}

	public double timeSec() {
		return 0.5;
	}

	public String cascadeClassifierXmlPath() {
		return "haarcascade_frontalface_alt.xml";
	};
	
	
	private String getBase64(Frame frame){
		try {
			//生成base64
			BufferedImage bi = java2dConvert.convert(frame);
			if(debug()){
				LogUtil.log(name()+" frame convert to BufferedImage:"+bi);
			}
			ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024);
			ImageIO.write(bi, "jpg", buffer);//jpg格式比png快很多很多。
			if(debug()){
				LogUtil.log(name()+" BufferedImage write to byteArray");
			}
			String base64 = Base64Util.encode(buffer.toByteArray());
			buffer.close();
			if(debug()){
				LogUtil.log(name()+" base64:"+base64);
			}
			return base64;
		} catch (Exception e) {}
		return null;
	}
}
